#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "sample_comm.h"
//#include "disp_ops.h"
#include "hi_mw_media_intf.h"
#include "app_common.h"

HI_HANDLE g_hACapHdl = 0;

static HI_BOOL s_abVPortStarted[5] = {HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE};//Vport(defined in ndk) means vpss chn(defined in sdk)
static HI_BOOL s_abVProcStarted[5] = {HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE};//Vproc(defined in ndk) means vpss grp(defined in sdk)
static HI_BOOL s_abVProcInited[5] = {HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE};
static HI_BOOL s_abVProcBinded[5] = {HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE};//Vproc bind means bind vi and vpss
static HI_BOOL s_abVEncPrepared[5] = {HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE};

static HI_S32 MW_Media_InitVB(HI_MW_VCapAttr_S* pstMWVCapAttr)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 u32BufSize = 0;
    VB_CONFIG_S stVbConf = {0};
    u32BufSize = COMMON_GetPicBufferSize(pstMWVCapAttr->WIDTH, pstMWVCapAttr->HEIGHT, SAMPLE_PIXEL_FORMAT,\
        DATA_BITWIDTH_8,COMPRESS_MODE_NONE,DEFAULT_ALIGN);
    stVbConf.u32MaxPoolCnt = 16;
    stVbConf.astCommPool[0].u64BlkSize = u32BufSize;
    stVbConf.astCommPool[0].u32BlkCnt = 4;

    u32BufSize = COMMON_GetPicBufferSize(640, 360, SAMPLE_PIXEL_FORMAT,\
        DATA_BITWIDTH_8,COMPRESS_MODE_NONE,DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize = 0; //src: u32BufSize
    stVbConf.astCommPool[1].u32BlkCnt = 0; //src:6
    
    u32BufSize = COMMON_GetPicBufferSize(320, 240, SAMPLE_PIXEL_FORMAT,\
        DATA_BITWIDTH_8,COMPRESS_MODE_NONE,DEFAULT_ALIGN);
    stVbConf.astCommPool[2].u64BlkSize = u32BufSize;
    stVbConf.astCommPool[2].u32BlkCnt = 2;
    
    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    return HI_SUCCESS;
}

static HI_VOID MW_Media_DeinitVB()
{
    SAMPLE_COMM_SYS_Exit();
}

static HI_S32 MW_Media_InitVI(HI_MW_SensorAttr_S* pstMWSensorAttr)
{
    HI_S32              s32Ret;
    ISP_CTRL_PARAM_S    stIspCtrlParam;
    SAMPLE_VI_CONFIG_S stViConfig = {0};

     SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);
    if(SAMPLE_SNS_TYPE_BUTT == stViConfig.astViInfo[0].stSnsInfo.enSnsType)
    {
        LOGE("Not set SENSOR%d_TYPE !\n",0);
        return HI_FALSE;
    }
    
    stViConfig.s32WorkingViNum       = 1;
    stViConfig.as32WorkingViId[0]    = 0;
    stViConfig.astViInfo[0].stDevInfo.ViDev     = 0;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[0] = 0;
    stViConfig.astViInfo[0].stChnInfo.ViChn     = 0;
    stViConfig.astViInfo[0].stChnInfo.enDynamicRange = DYNAMIC_RANGE_SDR8;
    stViConfig.astViInfo[0].stChnInfo.enPixFormat    = SAMPLE_PIXEL_FORMAT;
    stViConfig.astViInfo[0].stSnsInfo.MipiDev            = 0;
    stViConfig.astViInfo[0].stSnsInfo.s32BusId           = 0;
    stViConfig.astViInfo[0].stDevInfo.enWDRMode          = WDR_MODE_NONE;
    stViConfig.astViInfo[0].stPipeInfo.enMastPipeMode    = VI_ONLINE_VPSS_ONLINE;
    stViConfig.astViInfo[0].stChnInfo.enVideoFormat      = VIDEO_FORMAT_LINEAR;
    stViConfig.astViInfo[0].stChnInfo.enCompressMode     = COMPRESS_MODE_NONE;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[1]          = -1;
    s32Ret = SAMPLE_COMM_VI_SetParam(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("SAMPLE_COMM_VI_SetParam failed with %d!\n", s32Ret);
        return s32Ret;
    }

    s32Ret = HI_MPI_ISP_GetCtrlParam(stViConfig.astViInfo[0].stPipeInfo.aPipe[0], &stIspCtrlParam);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("HI_MPI_ISP_GetCtrlParam failed with %d!\n", s32Ret);
        return s32Ret;
    }
    stIspCtrlParam.u32StatIntvl  = pstMWSensorAttr->FRAMERATE/30;

    s32Ret = HI_MPI_ISP_SetCtrlParam(stViConfig.astViInfo[0].stPipeInfo.aPipe[0], &stIspCtrlParam);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("HI_MPI_ISP_SetCtrlParam failed with %d!\n", s32Ret);
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_COMM_SYS_Exit();
        LOGE("SAMPLE_COMM_VI_StartVi failed with %d!\n", s32Ret);
        return s32Ret;
    }

    return HI_SUCCESS;
}

static HI_VOID MW_Media_DeinitVI(HI_MW_SensorAttr_S* pstMWSensorAttr)
{
    HI_S32 s32Ret = HI_SUCCESS;
    SAMPLE_VI_CONFIG_S stViConfig = {0};

    stViConfig.s32WorkingViNum       = 1;
    stViConfig.as32WorkingViId[0]    = 0;
    stViConfig.astViInfo[0].stDevInfo.ViDev     = 0;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[0] = 0;
    stViConfig.astViInfo[0].stChnInfo.ViChn     = 0;
    stViConfig.astViInfo[0].stChnInfo.enDynamicRange = DYNAMIC_RANGE_SDR8;
    stViConfig.astViInfo[0].stChnInfo.enPixFormat    = SAMPLE_PIXEL_FORMAT;
    stViConfig.astViInfo[0].stSnsInfo.MipiDev            = 0;
    stViConfig.astViInfo[0].stSnsInfo.s32BusId           = 0;
    stViConfig.astViInfo[0].stDevInfo.enWDRMode          = WDR_MODE_NONE;
    stViConfig.astViInfo[0].stPipeInfo.enMastPipeMode    = VI_ONLINE_VPSS_ONLINE;
    stViConfig.astViInfo[0].stChnInfo.enVideoFormat      = VIDEO_FORMAT_LINEAR;
    stViConfig.astViInfo[0].stChnInfo.enCompressMode     = COMPRESS_MODE_NONE;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[1]          = -1;

    s32Ret = SAMPLE_COMM_VI_StopVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("SAMPLE_COMM_VI_StopVi failed with %d!\n", s32Ret);
    }
}

static HI_S32 MW_Media_CreateVPSSGrp(HI_MW_VProcAttr_S* pstVProcAttr)
{
    HI_S32 s32Ret = HI_SUCCESS;
    VPSS_GRP_ATTR_S stVpssGrpAttr = {0};

    stVpssGrpAttr.enDynamicRange          = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat           = SAMPLE_PIXEL_FORMAT;
    stVpssGrpAttr.u32MaxW                 = pstVProcAttr->WIDTH;
    stVpssGrpAttr.u32MaxH                 = pstVProcAttr->HEIGHT;
    stVpssGrpAttr.bNrEn                   = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enNrType       = VPSS_NR_TYPE_VIDEO;
    stVpssGrpAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;
    stVpssGrpAttr.stNrAttr.enCompressMode = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;

    s32Ret = HI_MPI_VPSS_CreateGrp(pstVProcAttr->HANDLE, &stVpssGrpAttr);
    if (s32Ret != HI_SUCCESS)
    {
        LOGE("HI_MPI_VPSS_CreateGrp(grp:%d) failed with %#x!\n", pstVProcAttr->HANDLE, s32Ret);
        return s32Ret;
    }

    return s32Ret;
}

static HI_S32 MW_Media_EnableVPSSChn(VPSS_GRP VpssGrp, HI_MW_VPortAttr* pstVPortAttr)
{
    HI_S32 s32Ret;
    VPSS_CHN_ATTR_S     stVpssChnAttr;

    memset(&stVpssChnAttr, 0, sizeof(VPSS_CHN_ATTR_S));
    stVpssChnAttr.u32Width                     = pstVPortAttr->WIDTH;
    stVpssChnAttr.u32Height                    = pstVPortAttr->HEIGHT;
    stVpssChnAttr.enChnMode                    = VPSS_CHN_MODE_USER;
    stVpssChnAttr.enCompressMode               = COMPRESS_MODE_NONE;
    stVpssChnAttr.enDynamicRange               = DYNAMIC_RANGE_SDR8;
    stVpssChnAttr.enPixelFormat                = SAMPLE_PIXEL_FORMAT;
//    stVpssChnAttr.stFrameRate.s32SrcFrameRate  = pstVPortAttr->FRAMERATE;
    stVpssChnAttr.stFrameRate.s32SrcFrameRate  = 30;
    stVpssChnAttr.stFrameRate.s32DstFrameRate  = pstVPortAttr->FRAMERATE;
    stVpssChnAttr.u32Depth                     = 0;
    stVpssChnAttr.bMirror                      = HI_FALSE;
    stVpssChnAttr.bFlip                        = HI_FALSE;
    stVpssChnAttr.enVideoFormat                = VIDEO_FORMAT_LINEAR;
    stVpssChnAttr.stAspectRatio.enMode         = ASPECT_RATIO_NONE;

    s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, pstVPortAttr->HANDLE, &stVpssChnAttr);
    if (s32Ret != HI_SUCCESS)
    {
        LOGE("HI_MPI_VPSS_SetChnAttr chan %d failed with %#x\n", pstVPortAttr->HANDLE, s32Ret);
        return s32Ret;
    }

    s32Ret = HI_MPI_VPSS_EnableChn(VpssGrp, pstVPortAttr->HANDLE);
    if (s32Ret != HI_SUCCESS)
    {
        LOGE("HI_MPI_VPSS_EnableChn (%d) failed with %#x\n", pstVPortAttr->HANDLE, s32Ret);
        return s32Ret;
    }

    return HI_SUCCESS;
}

static HI_VOID MW_Media_DeinitVPSS(HI_MW_VideoBindMap_S astVideoBindMap[], HI_U32 u32BindMapSize)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 i = 0;

    for (i = 0; i < u32BindMapSize; i++)
    {
        if (HI_TRUE == s_abVPortStarted[astVideoBindMap[i].pstVPortAttr->HANDLE])
        {
            s32Ret = HI_MPI_VPSS_DisableChn(astVideoBindMap[i].pstVProcAttr->HANDLE, astVideoBindMap[i].pstVPortAttr->HANDLE);
            if (HI_SUCCESS != s32Ret)
            {
                LOGE("HI_MPI_VPSS_DisableChn(grp:%d, chn:%d) failed with %#x!\n",\
                    astVideoBindMap[i].pstVProcAttr->HANDLE, astVideoBindMap[i].pstVPortAttr->HANDLE,s32Ret);
            }

            s_abVPortStarted[astVideoBindMap[i].pstVPortAttr->HANDLE] = HI_FALSE;
        }
    }

    for (i = 0; i < u32BindMapSize; i++)
    {
        if (HI_TRUE == s_abVProcStarted[astVideoBindMap[i].pstVProcAttr->HANDLE])
        {
            s32Ret = HI_MPI_VPSS_StopGrp(astVideoBindMap[i].pstVProcAttr->HANDLE);
            if (s32Ret != HI_SUCCESS)
            {
                LOGE("HI_MPI_VPSS_StopGrp failed with %#x!\n", s32Ret);
            }

            s_abVProcStarted[astVideoBindMap[i].pstVProcAttr->HANDLE] = HI_FALSE;
        }

        if (HI_TRUE == s_abVProcInited[astVideoBindMap[i].pstVProcAttr->HANDLE])
        {
            s32Ret = HI_MPI_VPSS_DestroyGrp(astVideoBindMap[i].pstVProcAttr->HANDLE);
            if (s32Ret != HI_SUCCESS)
            {
                LOGE("HI_MPI_VPSS_DestroyGrp failed with %#x!\n", s32Ret);
            }

            s_abVProcInited[astVideoBindMap[i].pstVProcAttr->HANDLE] = HI_FALSE;
        }
    }
}

static HI_S32 MW_Media_InitVPSS(HI_MW_VideoBindMap_S astVideoBindMap[], HI_U32 u32BindMapSize)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 i = 0;
    HI_BOOL bError = HI_FALSE;

    for (i = 0; i < u32BindMapSize; i++)
    {
        if (HI_FALSE == s_abVProcInited[astVideoBindMap[i].pstVProcAttr->HANDLE])
        {
            s32Ret = MW_Media_CreateVPSSGrp(astVideoBindMap[i].pstVProcAttr);
            if (s32Ret != HI_SUCCESS)
            {
                LOGE("MW_Media_CreateVPSSGrp(grp:%d) failed with %#x!\n", astVideoBindMap[i].pstVProcAttr->HANDLE, s32Ret);
                bError = HI_TRUE;
                break;;
            }

            s_abVProcInited[astVideoBindMap[i].pstVProcAttr->HANDLE] = HI_TRUE;
        }

        if (HI_FALSE == s_abVPortStarted[astVideoBindMap[i].pstVPortAttr->HANDLE])
        {
            s32Ret = MW_Media_EnableVPSSChn(astVideoBindMap[i].pstVProcAttr->HANDLE, astVideoBindMap[i].pstVPortAttr);
            if (HI_SUCCESS != s32Ret)
            {
                LOGE("MW_Media_EnableVPSSChn(chn:%d) failed with %#x!\n", astVideoBindMap[i].pstVPortAttr->HANDLE, s32Ret);
                bError = HI_TRUE;
                break;;
            }

            s_abVPortStarted[astVideoBindMap[i].pstVPortAttr->HANDLE] = HI_TRUE;
        }

        if (HI_FALSE == s_abVProcStarted[astVideoBindMap[i].pstVProcAttr->HANDLE])
        {
            s32Ret = HI_MPI_VPSS_StartGrp(astVideoBindMap[i].pstVProcAttr->HANDLE);
            if (s32Ret != HI_SUCCESS)
            {
                LOGE("HI_MPI_VPSS_StartGrp(grp:%d) failed with %#x!\n", astVideoBindMap[i].pstVProcAttr->HANDLE, s32Ret);
                bError = HI_TRUE;
                break;;
            }

            s_abVProcStarted[astVideoBindMap[i].pstVProcAttr->HANDLE] = HI_TRUE;
        }
    }

    if (bError)
    {
        MW_Media_DeinitVPSS(astVideoBindMap, u32BindMapSize);
    }

    return s32Ret;
}

static HI_S32 MW_Media_VIBindVPSS(VI_PIPE ViPipe, VI_CHN ViChn, VPSS_GRP VpssGrp)
{
    HI_S32 s32Ret = HI_SUCCESS;

    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("SAMPLE_COMM_VI_Bind_VPSS(ViPipe :%d, ViChn:%d, VpssGrp:%d) failed with %#x!\n", ViPipe, ViChn, VpssGrp, s32Ret);
        return s32Ret;
    }

    return HI_SUCCESS;
}

static HI_VOID MW_Media_VIUnBindVPSS(VI_PIPE ViPipe, VI_CHN ViChn, VPSS_GRP VpssGrp)
{
    HI_S32 s32Ret = HI_SUCCESS;

    s32Ret = SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("MW_Media_VIUnBindVPSS(ViPipe :%d, ViChn:%d, VpssGrp:%d) failed with %#x!\n", ViPipe, ViChn, VpssGrp, s32Ret);
    }
}

static HI_S32 MW_Media_CreateVENCChn(HI_HANDLE hVProcHandle, HI_MW_VPortAttr* pstVPortAttr, HI_MW_VEncAttr* pstVEncAttr)
{
    HI_S32 s32Ret = HI_SUCCESS;
    VENC_CHN_ATTR_S stVencAttr;
    memset(&stVencAttr, 0x00, sizeof(VENC_CHN_ATTR_S));
    VENC_CHN VeChn = pstVEncAttr->HANDLE;
    switch (pstVEncAttr->PAYLOAD_TYPE)
    {
        case HI_MW_PAYLOAD_TYPE_H264:
            stVencAttr.stVencAttr.enType = PT_H264;
            stVencAttr.stVencAttr.bByFrame = HI_TRUE;
            stVencAttr.stVencAttr.u32BufSize = pstVEncAttr->BUFSIZE;
            stVencAttr.stVencAttr.u32MaxPicHeight = pstVEncAttr->HEIGHT;
            stVencAttr.stVencAttr.u32MaxPicWidth = pstVEncAttr->WIDTH;
            stVencAttr.stVencAttr.u32PicHeight = pstVEncAttr->HEIGHT;
            stVencAttr.stVencAttr.u32PicWidth = pstVEncAttr->WIDTH;
            stVencAttr.stVencAttr.u32Profile = pstVEncAttr->PROFILE;
#if 0
            stVencAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
            stVencAttr.stRcAttr.stH264Cbr.fr32DstFrameRate = pstVEncAttr->FRAMERATE;
            stVencAttr.stRcAttr.stH264Cbr.u32SrcFrameRate = pstVEncAttr->FRAMERATE;
            stVencAttr.stRcAttr.stH264Cbr.u32Gop = pstVEncAttr->GOP;
            stVencAttr.stRcAttr.stH264Cbr.u32StatTime = 1;
            stVencAttr.stRcAttr.stH264Cbr.u32BitRate = pstVEncAttr->BITRATE;
#else
            stVencAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264VBR;
            stVencAttr.stRcAttr.stH264Vbr.fr32DstFrameRate = pstVEncAttr->FRAMERATE;
            stVencAttr.stRcAttr.stH264Vbr.u32SrcFrameRate = pstVEncAttr->FRAMERATE;
            stVencAttr.stRcAttr.stH264Vbr.u32Gop = pstVEncAttr->GOP;
            stVencAttr.stRcAttr.stH264Vbr.u32StatTime = 4;
            stVencAttr.stRcAttr.stH264Vbr.u32MaxBitRate = pstVEncAttr->BITRATE;
#endif
            break;
        case HI_MW_PAYLOAD_TYPE_H265:
            stVencAttr.stVencAttr.enType = PT_H265;
            stVencAttr.stVencAttr.bByFrame = HI_TRUE;
            stVencAttr.stVencAttr.u32BufSize = pstVEncAttr->BUFSIZE;
            stVencAttr.stVencAttr.u32MaxPicHeight = pstVEncAttr->HEIGHT;
            stVencAttr.stVencAttr.u32MaxPicWidth = pstVEncAttr->WIDTH;
            stVencAttr.stVencAttr.u32PicHeight = pstVEncAttr->HEIGHT;
            stVencAttr.stVencAttr.u32PicWidth = pstVEncAttr->WIDTH;
            stVencAttr.stVencAttr.u32Profile = pstVEncAttr->PROFILE;
            stVencAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR;
            stVencAttr.stRcAttr.stH265Cbr.fr32DstFrameRate = pstVEncAttr->FRAMERATE;
            stVencAttr.stRcAttr.stH265Cbr.u32SrcFrameRate = pstVEncAttr->FRAMERATE;
            stVencAttr.stRcAttr.stH265Cbr.u32Gop = pstVEncAttr->GOP;
            stVencAttr.stRcAttr.stH265Cbr.u32StatTime = 1;
            stVencAttr.stRcAttr.stH265Cbr.u32BitRate = pstVEncAttr->BITRATE;

            break;
        case HI_MW_PAYLOAD_TYPE_JPEG:
            stVencAttr.stVencAttr.enType = PT_JPEG;
            stVencAttr.stVencAttr.bByFrame = HI_TRUE;
            stVencAttr.stVencAttr.u32MaxPicHeight = pstVEncAttr->HEIGHT;
            stVencAttr.stVencAttr.u32MaxPicWidth = pstVEncAttr->WIDTH;
            stVencAttr.stVencAttr.u32PicHeight = pstVEncAttr->HEIGHT;
            stVencAttr.stVencAttr.u32PicWidth = pstVEncAttr->WIDTH;
            stVencAttr.stVencAttr.u32BufSize = pstVEncAttr->BUFSIZE;
            stVencAttr.stVencAttr.stAttrJpege.bSupportDCF = HI_FALSE;
            break;
        default:
            break;
    }
    //create venc chn.
    if (PT_JPEG != stVencAttr.stVencAttr.enType)
    {
        stVencAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP;
        stVencAttr.stGopAttr.stNormalP.s32IPQpDelta = 0;
    }
    s32Ret = HI_MPI_VENC_CreateChn(VeChn, &stVencAttr);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("HI_MPI_VENC_CreateChn %d ret %#x \n", VeChn, s32Ret);
        sleep(120);
        return s32Ret;
    }
    //bind venc and vpss.
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;
    stSrcChn.enModId = HI_ID_VPSS;
    stSrcChn.s32DevId = hVProcHandle;//vpssgrp
    stSrcChn.s32ChnId = pstVPortAttr->HANDLE;//vpsschn
    stDestChn.enModId = HI_ID_VENC;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = pstVEncAttr->HANDLE;//vencchn
    s32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);
    if (s32Ret != HI_SUCCESS)
    {
        LOGE("failed with %#x!\n", s32Ret);
        return s32Ret;
    }

    switch (pstVEncAttr->PAYLOAD_TYPE)
    {
        case HI_MW_PAYLOAD_TYPE_H264:
            {
                VENC_RC_PARAM_S stRcParam;
                memset(&stRcParam, 0, sizeof(stRcParam));
                s32Ret = HI_MPI_VENC_GetRcParam(VeChn, &stRcParam);
                if (HI_SUCCESS != s32Ret) {
                    LOGE("HI_MPI_VENC_GetRcParam vechn[%d] failed with %#x!\n", VeChn, s32Ret);
                        return s32Ret;
                }
                //LOGW("s32ChangePos:%d u32MinQp:%d u32MaxQp:%d\n", stRcParam.stParamH264Vbr.s32ChangePos, stRcParam.stParamH264Vbr.u32MinQp, stRcParam.stParamH264Vbr.u32MaxQp);
#if 0
                stRcParam.stParamH264Vbr.s32ChangePos = 85;
                stRcParam.stParamH264Vbr.u32MinQp = 28;
                stRcParam.stParamH264Vbr.u32MaxQp = 51;
#else
				stRcParam.u32RowQpDelta = 3;
                stRcParam.stParamH264Vbr.s32ChangePos = 85;
                stRcParam.stParamH264Vbr.u32MinQp = 33;
                stRcParam.stParamH264Vbr.u32MaxQp = 48;
                stRcParam.stParamH264Vbr.u32MinIQp = 33;
                stRcParam.stParamH264Vbr.u32MaxIQp = 48;
#endif
//                stRcParam.stParamH264Vbr.u32MaxQp = 40;
//                stRcParam.stParamH264Vbr.u32MinIQp = 24;
//                stRcParam.stParamH264Vbr.u32MaxIQp = 51;
                s32Ret = HI_MPI_VENC_SetRcParam(VeChn, &stRcParam);
                if (HI_SUCCESS != s32Ret) {
                    LOGE("HI_MPI_VENC_SetRcParam vechn[%d] failed with %#x!\n", VeChn, s32Ret);
                        return s32Ret;
                }
            }
            break;
        default:
            break;
    }
    
    return HI_SUCCESS;
}

static HI_VOID MW_Media_DeinitVENC(HI_MW_VideoBindMap_S astVideoBindMap[], HI_U32 u32BindMapSize)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 i = 0;

    for (i = 0; i < u32BindMapSize; i++)
    {
        if (HI_TRUE == s_abVEncPrepared[astVideoBindMap[i].pstVEncAttr->HANDLE])
        {
            s32Ret = SAMPLE_COMM_VPSS_UnBind_VENC(astVideoBindMap[i].pstVProcAttr->HANDLE, astVideoBindMap[i].pstVPortAttr->HANDLE,\
                astVideoBindMap[i].pstVEncAttr->HANDLE);
            if (HI_SUCCESS != s32Ret)
            {
                LOGE("SAMPLE_COMM_VPSS_UnBind_VENC(vpssgrp:%d, vpsschn:%d, vencchn:%d)failed with %#x!\n",\
                    astVideoBindMap[i].pstVProcAttr->HANDLE,astVideoBindMap[i].pstVPortAttr->HANDLE, astVideoBindMap[i].pstVEncAttr->HANDLE, s32Ret);
            }

            s32Ret = HI_MPI_VENC_DestroyChn(astVideoBindMap[i].pstVEncAttr->HANDLE);
            if (HI_SUCCESS != s32Ret)
            {
                LOGE("HI_MPI_VENC_DestroyChn vechn[%d] failed with %#x!\n", \
                           astVideoBindMap[i].pstVEncAttr->HANDLE, s32Ret);
            }

            s_abVEncPrepared[astVideoBindMap[i].pstVEncAttr->HANDLE] = HI_FALSE;
        }
    }
}

static HI_S32 MW_Media_InitVENC(HI_MW_VideoBindMap_S astVideoBindMap[], HI_U32 u32BindMapSize)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 i = 0;
    HI_BOOL bError = HI_FALSE;

    for (i = 0; i < u32BindMapSize; i++)
    {
        if (HI_FALSE == s_abVEncPrepared[astVideoBindMap[i].pstVEncAttr->HANDLE])
        {
            s32Ret = MW_Media_CreateVENCChn(astVideoBindMap[i].pstVProcAttr->HANDLE, astVideoBindMap[i].pstVPortAttr, astVideoBindMap[i].pstVEncAttr);
            if (HI_SUCCESS != s32Ret)
            {
                LOGE("call MW_Media_CreateVENCChn for %u fail, and ret %x\n", i,s32Ret);
                bError = HI_TRUE;
                break;
            }

            s_abVEncPrepared[astVideoBindMap[i].pstVEncAttr->HANDLE] = HI_TRUE;
        }
    }

    if (bError)
    {
        MW_Media_DeinitVENC(astVideoBindMap, u32BindMapSize);
        return s32Ret;
    }

    return HI_SUCCESS;
}

HI_S32 HI_MW_Media_StartVenc(HI_MW_VideoBindMap_S *pstVideoBindMap)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_BOOL bError = HI_FALSE;

	if (HI_FALSE == s_abVEncPrepared[pstVideoBindMap->pstVEncAttr->HANDLE])
	{
		s32Ret = MW_Media_CreateVENCChn(pstVideoBindMap->pstVProcAttr->HANDLE, pstVideoBindMap->pstVPortAttr, pstVideoBindMap->pstVEncAttr);
		if (HI_SUCCESS != s32Ret)
		{
			LOGE("call MW_Media_CreateVENCChn for fail, and ret %x\n", s32Ret);
			bError = HI_TRUE;
			goto err_out;
		}

        VENC_RECV_PIC_PARAM_S stRecvParam;
        stRecvParam.s32RecvPicNum = -1;
        s32Ret = HI_MPI_VENC_StartRecvFrame(pstVideoBindMap->pstVEncAttr->HANDLE, &stRecvParam);
        if (HI_SUCCESS != s32Ret) {
            LOGE("HI_MPI_VENC_StartRecvFrame %lu ret %#x\n", pstVideoBindMap->pstVEncAttr->HANDLE,s32Ret);
            goto err_out;
        }

        HI_MW_VEnc_StreamSwitch(pstVideoBindMap->pstVEncAttr->HANDLE, HI_TRUE);
        
		s_abVEncPrepared[pstVideoBindMap->pstVEncAttr->HANDLE] = HI_TRUE;
		
		return s32Ret;
	}

err_out:
    if (bError)
    {
        HI_MW_Media_StopVenc(pstVideoBindMap);
        return s32Ret;
    }	

    return HI_SUCCESS;
}

HI_S32 HI_MW_Media_StopVenc(HI_MW_VideoBindMap_S *pstVideoBindMap)
{
    HI_S32 s32Ret = HI_SUCCESS;
 
	if (HI_TRUE == s_abVEncPrepared[pstVideoBindMap->pstVEncAttr->HANDLE])
	{
	     HI_MW_VEnc_StreamSwitch(pstVideoBindMap->pstVEncAttr->HANDLE, HI_FALSE);
	     
		s32Ret = SAMPLE_COMM_VPSS_UnBind_VENC(pstVideoBindMap->pstVProcAttr->HANDLE, pstVideoBindMap->pstVPortAttr->HANDLE,\
			pstVideoBindMap->pstVEncAttr->HANDLE);
		if (HI_SUCCESS != s32Ret)
		{
			LOGE("SAMPLE_COMM_VPSS_UnBind_VENC(vpssgrp:%d, vpsschn:%d, vencchn:%d)failed with %#x!\n",\
				pstVideoBindMap->pstVProcAttr->HANDLE, pstVideoBindMap->pstVPortAttr->HANDLE, pstVideoBindMap->pstVEncAttr->HANDLE, s32Ret);
		}

        s32Ret = HI_MPI_VENC_StopRecvFrame(pstVideoBindMap->pstVEncAttr->HANDLE);
        if (HI_SUCCESS != s32Ret) {
            LOGE("HI_MPI_VENC_StopRecvFrame %lu ret %#x\n", pstVideoBindMap->pstVEncAttr->HANDLE, s32Ret);
        }

		s32Ret = HI_MPI_VENC_DestroyChn(pstVideoBindMap->pstVEncAttr->HANDLE);
		if (HI_SUCCESS != s32Ret)
		{
			LOGE("HI_MPI_VENC_DestroyChn vechn[%d] failed with %#x!\n", \
					   pstVideoBindMap->pstVEncAttr->HANDLE, s32Ret);
		}

		s_abVEncPrepared[pstVideoBindMap->pstVEncAttr->HANDLE] = HI_FALSE;
	}
   
	return 0;
}

HI_S32 HI_MW_Media_Init(HI_MW_SensorAttr_S* pstMWSensorAttr,
                        HI_MW_VCapAttr_S* pstMWVCapAttr,
                        HI_MW_VideoBindMap_S astVideoBindMap[], HI_U32 u32BindMapSize,
                        HI_HANDLE hACapHdl, HI_HANDLE hAEncHdl)
{
    HI_S32 s32Ret = HI_SUCCESS;
    VI_PIPE ViPipe = 0;
    VI_CHN  ViChn  = 0;
    VPSS_GRP VpssGrp = astVideoBindMap[0].pstVProcAttr->HANDLE;

    s32Ret = MW_Media_InitVB(pstMWVCapAttr);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("MW_Media_InitVB err for %#x!\n", s32Ret);
        return s32Ret;
    }

    s32Ret = MW_Media_InitVI(pstMWSensorAttr);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("MW_Media_InitVI err for %#x!\n", s32Ret);
        return s32Ret;
    }

    s32Ret = MW_Media_InitVPSS(astVideoBindMap, u32BindMapSize);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("MW_Media_InitVPSS err for %#x!\n", s32Ret);
        goto EXIT_VI_DEINIT;
    }

    s32Ret = MW_Media_VIBindVPSS(ViPipe, ViChn, VpssGrp);
    if(HI_SUCCESS != s32Ret)
    {
        LOGE("VI Bind VPSS err for %#x!\n", s32Ret);
        goto EXIT_VPSS_DEINIT;
    }

    s32Ret = MW_Media_InitVENC(astVideoBindMap, u32BindMapSize);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("MW_Media_InitVENC err for %#x!\n", s32Ret);
        goto EXIT_VI_VPSS_UNBIND;
    }

    return HI_SUCCESS;
EXIT_VENC_DEINIT:
    MW_Media_DeinitVENC(astVideoBindMap, u32BindMapSize);
EXIT_VI_VPSS_UNBIND:
    MW_Media_VIUnBindVPSS(ViPipe,ViChn,VpssGrp);
EXIT_VPSS_DEINIT:
    MW_Media_DeinitVPSS(astVideoBindMap, u32BindMapSize);
EXIT_VI_DEINIT:
    MW_Media_DeinitVI(pstMWSensorAttr);
    MW_Media_DeinitVB();

    return s32Ret;
}

HI_S32 HI_MW_Media_DeInit(__attribute__((unused)) HI_MW_SensorAttr_S* pstMWSensorAttr,
                          HI_MW_VCapAttr_S* pstMWVCapAttr,
                          HI_MW_VideoBindMap_S astVideoBindMap[], HI_U32 u32BindMapSize,
                          HI_HANDLE hACapHdl, HI_HANDLE hAEncHdl)
{
    VI_PIPE ViPipe = 0;
    VI_CHN  ViChn  = 0;
    VPSS_GRP VpssGrp = astVideoBindMap[0].pstVProcAttr->HANDLE;

    MW_Media_DeinitVENC(astVideoBindMap, u32BindMapSize);
    MW_Media_VIUnBindVPSS(ViPipe,ViChn,VpssGrp);
    MW_Media_DeinitVPSS(astVideoBindMap, u32BindMapSize);
    MW_Media_DeinitVI(pstMWSensorAttr);
    MW_Media_DeinitVB();
    return HI_SUCCESS;
}

HI_S32 HI_MW_DISP_Open(HI_VOID)
{
    SAMPLE_VO_CONFIG_S stVoDevInfo;

    HI_S32 s32Ret = HI_MW_Sys_Init();
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("HI_MW_Sys_Init failed with %d!\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = SAMPLE_COMM_VO_GetDefConfig(&stVoDevInfo);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("SAMPLE_COMM_VO_GetDefConfig failed with %d!\n", s32Ret);
        return HI_FAILURE;
    }

    stVoDevInfo.enDstDynamicRange = DYNAMIC_RANGE_SDR8;
    stVoDevInfo.enVoIntfType = VO_INTF_BT1120;
    stVoDevInfo.enIntfSync   = VO_OUTPUT_1080P25;

    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoDevInfo);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("SAMPLE_COMM_VO_StartVO failed with %d!\n", s32Ret);
        return HI_FAILURE;
    }

    return s32Ret;
}

HI_S32 HI_MW_DISP_Close(HI_VOID)
{
    HI_S32 s32Ret = HI_MW_Sys_Deinit();

    if (HI_SUCCESS != s32Ret)
    {
        LOGE("HI_MW_Sys_Deinit failed with %d!\n", s32Ret);
        return HI_FAILURE;
    }

    return s32Ret;
}

HI_S32 HI_MW_VO_Open(HI_HANDLE hVpssGrpHdl, HI_HANDLE hVpssChnHdl,
                     HI_HANDLE hDispHdl, HI_HANDLE hWndHdl, HI_U32 u32Width, HI_U32 u32Height)
{
    return DISP_OPEN(HI_FALSE, hVpssGrpHdl, hVpssChnHdl, hDispHdl, hWndHdl, u32Width, u32Height);
}

HI_S32 HI_MW_VO_Close(HI_HANDLE hVpssGrpHdl, HI_HANDLE hVpssChnHdl,
                      HI_HANDLE hDispHdl, HI_HANDLE hWndHdl)
{
    return DISP_Close(HI_FALSE, hVpssGrpHdl, hVpssChnHdl, hDispHdl, hWndHdl);
}

HI_S32 HI_MW_AO_Open(HI_HANDLE hAoHdl, HI_S32 s32SampleRate, HI_U32 u32ChnCnt)
{
    AO_OPEN(hAoHdl, s32SampleRate, u32ChnCnt);
    return HI_SUCCESS;
}


HI_S32 HI_MW_AO_Close(HI_HANDLE hAoHdl)
{
    AO_CLOSE(hAoHdl);
    return HI_SUCCESS;
}

HI_S32 HI_MW_AO_GetDevHandle(HI_HANDLE *phAoHdl)
{
    *phAoHdl = 0;
    return HI_SUCCESS;
}


HI_S32 HI_MW_VB_Alloc(HI_U32* pPoolId, HI_U32 u32FrameSize, HI_U32 u32FrameCnt)
{
    return HI_SUCCESS;
}

HI_S32 HI_MW_VB_Free(HI_U32 poolid)
{
    return HI_SUCCESS;
}

HI_S32 HI_MW_Sys_Init(HI_VOID)
{
    VB_CONFIG_S stVbConf = {0};
    stVbConf.u32MaxPoolCnt = 1;
    stVbConf.astCommPool[0].u64BlkSize = 1920 * 1080*2;
    stVbConf.astCommPool[0].u32BlkCnt = 4;
    HI_S32 s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }
    return HI_SUCCESS;
}

HI_S32 HI_MW_Sys_Deinit(HI_VOID)
{
    SAMPLE_COMM_SYS_Exit();
    return HI_SUCCESS;
}

HI_S32 HI_MW_DISP_SetDisplayGraphicCSC()
{
    return HI_SUCCESS;
}

HI_S32 HI_MW_TP_Open(HI_S32* ps32Fd)
{
    return HI_SUCCESS;
}

HI_S32 HI_MW_TP_Close(HI_VOID)
{
    return HI_SUCCESS;
}

HI_S32 HI_MW_TP_ReadData(MW_TOUCH_INPUTINFO_S* pstInputData)
{
    return HI_SUCCESS;
}
